"""
自定义的分页组件， 以后如果想要使用分页组件，需要如下：

在视图函数中（views.py）：

    def num_list(request):

        # 1. 根据直实需求筛选需要的数据
        queryset = models.PrettyNum.objects.all()

        # 2. 实例化分页对象
        page_object = Pagination(request, queryset)

        # 3. 返回到html的数据
        context = {
                # 分完页的数据
                'queryset': page_object.page_queryset,
                # 数据计数
                'count': queryset.count(),
                # 生成页码
                'page_string': page_object.html(),
            }
        return render(request, 'num_list.html', context=context)

在HTML页面中

    {% for obj in queryset %}
        {{ obj.xx }}
    {% endfor %}


    <ul class="pagination">
        {{ page_string }}
    </ul>

"""

from django.utils.safestring import mark_safe
import copy


class Pagination(object):

    def __init__(self, request, queryset, page_size=10, page_param='page', plus=3):
        """
        :param request: 请求的对象，需要传入
        :param queryset: 符合条件的查询数据（根据这个数据进行分布处理），需要传入
        :param page_size: 每页多少条数据，如不传入默认是10条
        :param page_param: 在URL里传递的获取分页的参数，例如：/prettynum/list/?page=4
        :param plus: 显示当前选中页的 前后各几页
        """

        # 拿到浏览器 get方式传过来的page， 不需要传入
        page = request.GET.get(page_param, '1')
        # 判断页码，如果是数字，int转换
        if page.isdecimal():
            page = int(page)
        else:
            # 非数字 赋值为1
            page = 1
        # 当前页
        self.page = page
        # 每页显示的数据条数
        self.page_size = page_size
        # 显示分页数据起始值和结束值
        # 规律：当前页码-1*10 到 当前页码*10
        self.start = (page - 1) * page_size
        self.end = page * page_size
        # 分完页的数据
        # queryset 是 对象传入的参数：根据条件筛选的数据，
        # [self.start:self.end]-包含了数据起始值和结束值]
        self.page_queryset = queryset[self.start:self.end]
        # 计算总条数
        self.count = queryset.count()
        # 计算总页码 self.total_page_count    # 除法，divmod 取商和余数
        self.total_page_count, self.div = divmod(self.count, page_size)
        if self.div > 0:
            self.total_page_count += 1
        # 显示当前页的 前5页 和 后5页
        self.plus = plus

        # 拼接 url传过来的GET参数
        # 生拷贝了一份request.GET
        query_dict = copy.deepcopy(request.GET)
        # 修改源码，允许修改
        from django.http.request import QueryDict
        query_dict._mutable = True
        # 包含了原来的url参数（比如：搜索条件）
        self.query_dict = query_dict
        # 增加的带页码的参数
        self.page_param = page_param

    def html(self):
        # 计算出，
        # 如果总页码小于等于 11 页，就在一页显示完所有页码，合计11页码
        if self.total_page_count <= self.plus * 2 + 1:
            # 起始页
            start_page = 1
            # 结尾页
            end_page = self.total_page_count
        # 超过11页 显示前5，当前和后5
        else:
            # 当前页小于5，防止起始页出现 -负数
            if self.page <= self.plus:
                start_page = 1
                end_page = self.plus * 2 + 1
            else:
                # 当前页 +5 > 总页码的情况：
                if (self.page + self.plus) > self.total_page_count:
                    start_page = self.page - self.plus
                    end_page = self.total_page_count
                else:
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus

        # 后台需要生成的html标签页码
        page_str_list = []  # [‘li标签1’,'li标签2',......'li标签19']

        # 首页
        self.query_dict.setlist(self.page_param, [1])
        page_str_list.append('<li ><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))

        # 上一页   page 是当前页 -1前一页 , 格式化字符串
        if self.page > 1:
            self.query_dict.setlist(self.page_param, [self.page - 1])
            prev = '<li ><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
        else:
            self.query_dict.setlist(self.page_param, [1])
            prev = '<li ><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(prev)

        # 页面
        # range 前取后不取，所以+1
        # for i in range(1, total_page_count+1):
        for i in range(start_page, end_page + 1):
            self.query_dict.setlist(self.page_param, [i])
            # ?page=值
            # 如果循环到当前页，增加一个 class="active" 样式，高亮显示激活状态
            if i == self.page:
                ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            else:
                ele = '<li ><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            page_str_list.append(ele)

        # 下一页 当前页小于总页数
        if self.page < self.total_page_count:
            self.query_dict.setlist(self.page_param, [self.page + 1])
            next = '<li ><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
        else:
            self.query_dict.setlist(self.page_param, [self.total_page_count])
            next = '<li ><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(next)

        # 尾页
        self.query_dict.setlist(self.page_param, [self.total_page_count])
        page_str_list.append('<li ><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))

        # 跳转
        skip_string = """
                <li>
                    <form method="get" style="float: left; margin-left: -1px">
                        <input name="page"
                               style="position: relative; float: left; display: inline-block;width: 80px; border-radius: 0"
                               type="text" class="form-control" placeholder="页码">
                        <button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
                    </form>
                </li>
                """

        page_str_list.append(skip_string)

        # diango 框架下，直接写html格式，需要标记 mark_safe
        # from django.utils.safestring import mark_safe
        # 标记安全的字符串转html标签 make_safe 需要导入
        # join() 将元素按照分隔符「拼接」成新的字符串, ''空分隔符
        # 传到前端
        page_string = mark_safe(''.join(page_str_list))
        # 将 page_string 返回到前端
        return page_string
